package com.penngo.gui.dfdiff.view;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ClassUtil;
import com.penngo.gui.dfdiff.DFMain;
import com.penngo.gui.dfdiff.utils.*;
import org.fife.ui.rsyntaxtextarea.AbstractJFlexCTokenMaker;
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
import org.fife.ui.rtextarea.RTextScrollPane;
import org.fife.ui.rtextarea.SearchContext;
import org.fife.ui.rtextarea.SearchEngine;
import org.jdesktop.swingx.autocomplete.AutoCompleteDecorator;
import org.jdesktop.swingx.combobox.ListComboBoxModel;
import javax.swing.*;
import javax.swing.text.JTextComponent;
import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.lang.reflect.Field;
import java.util.*;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;

/**
 * 文本编辑
 */
public class FileEditorPanel extends JPanel {
    private static Logger log = LogUtils.getLogger(FileEditorPanel.class);
    private JTextField searchField;
    private JCheckBox regexCB;
    private JCheckBox matchCaseCB;
    private JToolBar findBar;
    private RSyntaxTextArea textArea;
    private RTextScrollPane scrollPane;
    private JComboBox<String> styleComboBox;
    private JLabel rowValueLabel;
    private JLabel columnValueLabel;
    private String textStyle = "text/plain";
    private File file = null;
    public static Map<String, Object> styles;


    public FileEditorPanel(File file) {
        this.setLayout(new BorderLayout());
        initFindPanel();
        initPanel();
        initStatusPanel();
        //setTransferHandler(DFMain.handler);
        styleComboBox.setSelectedItem(SyntaxConstants.SYNTAX_STYLE_NONE);
        if(file != null){
            this.file = file;
            String text = FileUtil.readString(file, ToolUtil.getFileCharset(file));
            textArea.setText(text);
            if(text.length() > 0){
                textArea.setCaretPosition(0);
            }
            String ext = FileUtil.getSuffix(file);
            ToolUtil.getFileExtension().forEach((k,v)->{
                if(v.contains(ext)){
                    textArea.setSyntaxEditingStyle(k);
                    styleComboBox.setSelectedItem(k);
                }

            });
        }
    }
    private void initFindPanel(){
//        Font font = Config.getFont().deriveFont(12.0f);
        FindActionListener action = new FindActionListener();
        // Create a toolbar with searching options.
        findBar = new JToolBar();
//        findBar.setFont(font);
        searchField = new JTextField(30);
        findBar.add(searchField);
        final JButton nextButton = new JButton("向下搜索");
        nextButton.setActionCommand("FindNext");
        nextButton.addActionListener(action);
        findBar.add(nextButton);
        searchField.addActionListener(e -> nextButton.doClick(0));
        JButton prevButton = new JButton("向上搜索");
        prevButton.setActionCommand("FindPrev");
        prevButton.addActionListener(action);
        findBar.add(prevButton);
        regexCB = new JCheckBox("正则");
        findBar.add(regexCB);
        matchCaseCB = new JCheckBox("大小写");
        findBar.add(matchCaseCB);
        findBar.add(new JLabel("  "));
        JLabel closeLabel = new JLabel(ImgUtil.IMAGE_CLOSE);
        closeLabel.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
//                super.mouseClicked(e);
                setFindBarVisiable(false);
            }
        });

        findBar.add(closeLabel);

        add(findBar, BorderLayout.NORTH);
        setFindBarVisiable(false);
    }
    public void setFindBarVisiable(boolean b){
        findBar.setVisible(b);
    }
    class FindActionListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {

            // "FindNext" => search forward, "FindPrev" => search backward
            String command = e.getActionCommand();
            boolean forward = "FindNext".equals(command);

            // Create an object defining our search parameters.
            SearchContext context = new SearchContext();
            String text = searchField.getText();
            if (text.length() == 0) {
                return;
            }
            context.setSearchFor(text);
            context.setMatchCase(matchCaseCB.isSelected());
            context.setRegularExpression(regexCB.isSelected());
            context.setSearchForward(forward);
            context.setWholeWord(false);

            boolean found = SearchEngine.find(textArea, context).wasFound();
            if (!found) {
                JOptionPane.showMessageDialog(null, "找不到\"" + text + "\"");
            }

        }
    }

    private void initPanel() {
        textArea = new RSyntaxTextArea();
        textArea.setCodeFoldingEnabled(true);
        textArea.setAntiAliasingEnabled(true);
        textArea.setFont(Config.getFont());
        textArea.setLineWrap(Config.isIsLineWrap());

        textArea.addCaretListener(e -> {
            try
            {
                int pos = textArea.getCaretPosition();
                //获取行数
                int row = textArea.getLineOfOffset(pos) + 1;
                //获取列数
                int col = pos - textArea.getLineStartOffset(row - 1) + 1;
                rowValueLabel.setText(String.valueOf(row));
                columnValueLabel.setText(String.valueOf(col));
            }
            catch(Exception ex){
                log.log(Level.SEVERE, "   无法获得当前光标位置 ", ex);
            }
        });
        scrollPane = new RTextScrollPane(textArea);
        this.add(scrollPane, BorderLayout.CENTER);
    }

    /**
     * 状态栏
     */
    private void initStatusPanel() {
        JPanel panel = new JPanel(new GridBagLayout());
        JLabel rowTextLabel = new JLabel("行：");
        rowValueLabel = new JLabel(" ");
        panel.add(rowTextLabel, new GB(0, 0, 1, 1));
        panel.add(rowValueLabel, new GB(1, 0, 1, 1));

        JLabel columnTextLabel = new JLabel(" 列：");
        columnValueLabel = new JLabel(" ");
        panel.add(columnTextLabel, new GB(2, 0, 1, 1));
        panel.add(columnValueLabel, new GB(3, 0, 1, 1));

        panel.add(new JPanel(), new GB(4, 0, 1, 1).setFill(GB.BOTH).setWeight(100, 0));

        java.util.List<String> styleList = getStyle().keySet().stream().collect(Collectors.toList());
//        panel.add(new JPanel(), new GB(5, 0, 1, 1).setFill(GB.BOTH).setWeight(100, 0));

        // 类型
        styleComboBox = new JComboBox<>();
        AutoCompleteDecorator.decorate(styleComboBox);
        styleComboBox.setMaximumRowCount(35);
        styleComboBox.setModel(new ListComboBoxModel<String>(styleList));
        styleComboBox.addItemListener((ItemEvent e) -> {
            Object item = e.getItem();
            if (e.getStateChange() == ItemEvent.SELECTED) {
                textArea.setSyntaxEditingStyle(item.toString());
            }
        });
        panel.add(styleComboBox, new GB(5, 0, 1, 1).setInsets(5));


        this.add(panel, BorderLayout.SOUTH);
    }

    public String getText() {
        return textArea.getText();
    }

    public static Map<String, Object> getStyle(){
        styles = new TreeMap<>(Comparator.naturalOrder());

        List<Object> list = ToolUtil.getStyle();
        for(int i = 0; i + 3 < list.size(); i = i + 3){
            styles.put((String)list.get(i), list.get(i + 2));
        }
        return styles;
    }

    public File getFile() {
        return file;
    }

    public void setFile(File file) {
        this.file = file;
    }

    public static int getRows(JTextComponent txtCmp) {
        FontMetrics fm = txtCmp.getFontMetrics(txtCmp.getFont());

        int fontHeight = fm.getHeight();

        int ybaseline = txtCmp.getY() + fm.getAscent();
        int yend = ybaseline + txtCmp.getHeight();

        int rows = 1;

        while (ybaseline < yend) {
            ybaseline += fontHeight;
            rows++;
        }

        return rows;
    }

    public static void main(String[] args) {

        Field[] fields = SyntaxConstants.class.getDeclaredFields();

        try {
            for (Field field : fields) {
                String style = field.get(SyntaxConstants.class).toString();
                String name = style.substring(style.indexOf("/") + 1); // 去掉text/
                //styles.put(style, "");
//                System.out.println("\"" + name + "\",\"" + style + "\"");
                System.out.println("\"" + style + "\",");
            }
//            org.fife.ui.rsyntaxtextarea.modes.PHPTokenMaker
            getClassByPackage("org.fife.ui.rsyntaxtextarea.modes");
//            ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
//            URL[] urls = ((URLClassLoader) classLoader).getURLs();
//            for(URL url:urls){
//                System.out.println("url======" + url);
//            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static Class[] getClassByPackage(String packageName) {
        try {
            //获取所有的模型实现类
            Set<Class<?>> classes = ClassUtil.scanPackage("org.fife.ui.rsyntaxtextarea.modes");

            Map<String, AbstractJFlexCTokenMaker> map = new HashMap<>(classes.size());
            for (Class<?> aClass : classes) {
                //实例化
                String strs[] = aClass.toString().split("\\.");
                System.out.println(strs[strs.length -1] + ".class, ");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public RSyntaxTextArea getTextArea() {
        return textArea;
    }
}
